package denaris.core.controller;

import denaris.core.AbstractDenarisMap;
import denaris.midlet.DenarisGameCanvas;
import denaris.midlet.DenarisGameCanvas.DisplayProperties;

/**
 * The PlayerController is THE controller that alters the position of its
 * assigned Controllable depending on the current keyboard state. It is
 * responsible for checking colissions with the display border.
 * 
 * @author stkl23
 * 
 */
public class PlayerController extends AbstractController {
	public static int PLAYER_SPEED = 3;

	/** the frame sequence for moving the ship up */
	private int[] framesUp = { 0, 1, 1, 2 };

	/** the frame sequence for moving the ship down */
	private int[] framesDown = { 0, 3, 3, 4 };

	/** the map is needed to control vertical scrolling */
	private AbstractDenarisMap map;
	
	/** indicates the vertical position where the map starts scrolling in case it is too high to fit in the display */
	private int[] scrollArea = new int[2];
	/**
	 * the last keyboard state for detecting state changes which must result in
	 * resetting the frame index
	 */
	private int previousState = -1;

	public PlayerController(AbstractDenarisMap parentMap) {
		super();
		// adjust the scope
		scope[SCOPE_WIDTH] -= 30;
		scope[SCOPE_Y2] -= 12;
		scrollArea[0] = scope[SCOPE_Y] + 80;
		scrollArea[1] = scope[SCOPE_Y2] - 80;
		map = parentMap;
	}

	/**
	 * Moves the frame index "forward" within a frame seqeuence
	 * 
	 * @param c
	 * @param frames
	 */
	private void forward(int[] frames) {
		if (frameIndex < frames.length - 1) {
			frameIndex++;
		}
		controllable.setFrame(frames[frameIndex]);
	}

	/**
	 * Moves the frame index "backward" within a frame seqeuence
	 * 
	 * @param c
	 * @param frames
	 */
	private void backward(int[] frames) {
		if (frameIndex > 0) {
			frameIndex--;
		}
		controllable.setFrame(frames[frameIndex]);
	}

	/**
	 * Implements the control of the players ship via the given key states.
	 */
	public boolean advance() {
		boolean result = true;
		int state = -1;
		int dx = 0;
		int dy = 0;

		if (DenarisGameCanvas.keyStates[DenarisGameCanvas.KEY_UP]) {
			// move up
			// scroll up?
			if (controllable.getY() <= scrollArea[0] && map.getY() < DisplayProperties.GAME_TOP) {
				// yes
				int diff = DisplayProperties.GAME_TOP - map.getY();
				map.move(0, diff > PLAYER_SPEED ? PLAYER_SPEED : diff);
			}else {
				dy = controllable.getY() > (scope[SCOPE_Y] + PLAYER_SPEED) ? -PLAYER_SPEED : 0;
			}
			// animate
			state = DenarisGameCanvas.KEY_UP;
			if (previousState != state) {
				// state change - reset frame index
				frameIndex = 0;
			}
			forward(framesUp);
		}

		if (DenarisGameCanvas.keyStates[DenarisGameCanvas.KEY_DOWN]) {
			// move down
			// scroll ?
			if (controllable.getY() >= scrollArea[1] && map.getHeight() > scope[SCOPE_Y2]){
				int diff = (map.getY() + map.getHeight()) - scope[SCOPE_Y2];
				map.move(0, diff > PLAYER_SPEED ? -PLAYER_SPEED : -diff);
			}else {
				dy = controllable.getY() < scope[SCOPE_Y2] - PLAYER_SPEED ? PLAYER_SPEED	: 0;
			}
			// animate
			state = DenarisGameCanvas.KEY_DOWN;
			if (previousState != state) {
				// state change - reset frame index
				frameIndex = 0;
			}
			forward(framesDown);
		}

		// reverse animation in case neither up nor down key is down
		if (!DenarisGameCanvas.keyStates[DenarisGameCanvas.KEY_DOWN]
				&& !DenarisGameCanvas.keyStates[DenarisGameCanvas.KEY_UP]) {
			if (previousState == DenarisGameCanvas.KEY_UP) {
				backward(framesUp);
			} else {
				backward(framesDown);
			}
		}

		if (DenarisGameCanvas.keyStates[DenarisGameCanvas.KEY_RIGHT]) {
			// move right
			dx = controllable.getX() < scope[SCOPE_WIDTH] - PLAYER_SPEED ? PLAYER_SPEED	: 0;
		}

		if (DenarisGameCanvas.keyStates[DenarisGameCanvas.KEY_LEFT]) {
			// move left
			dx = controllable.getX() > PLAYER_SPEED ? -PLAYER_SPEED : 0;
		}

		controllable.move(dx, dy);

		previousState = state;

		return result;
	}
	
	public void reset() {
		// reset all key states and indexes
		DenarisGameCanvas.keyStates[DenarisGameCanvas.KEY_UP] = false;
		DenarisGameCanvas.keyStates[DenarisGameCanvas.KEY_RIGHT] = false;
		DenarisGameCanvas.keyStates[DenarisGameCanvas.KEY_DOWN] = false;
		DenarisGameCanvas.keyStates[DenarisGameCanvas.KEY_LEFT] = false;
		DenarisGameCanvas.keyStates[DenarisGameCanvas.KEY_FIRE] = false;
		
		frameIndex = 0;
		// reset position
		controllable.setPosition(20, DisplayProperties.GAME_TOP + (DisplayProperties.GAME_HEIGHT >> 1));
		controllable.setFrame(0);
		// reset speed
		PLAYER_SPEED = 3;
	}
}
